<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>地图上框选范围</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/8.2.0/ol.min.css"
    integrity="sha512-bc9nJM5uKHN+wK7rtqMnzlGicwJBWR11SIDFJlYBe5fVOwjHGtXX8KMyYZ4sMgSL0CoUjo4GYgIBucOtqX/RUQ=="
    crossorigin="anonymous" referrerpolicy="no-referrer" />
  <style type="text/css">
    * {
      padding: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body,
    html {
      width: 100%;
      height: 100%;
      margin: 0;
      font-family: "Microsoft YaHei"
    }

    #map,
    #app {
      width: 100vw;
      height: 100vh;
    }

    #info {
      position: fixed;
      right: 10px;
      top: 10px;
      background-color: #fff;
      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
      width: 250px;
      padding: 10px;
      text-align: center;
      border-radius: 5px;
    }

    button {
      font-size: 18px;
      border: none;
      padding: 12px 20px;
      border-radius: 4px;
      color: #fff;
      background-color: #409eff;
      border-color: #409eff;
      cursor: pointer;
      border: 1px solid #dcdfe6;
    }

    p {
      position: fixed;
      left: 10px;
      top: 10px;
      z-index: 2;
      padding: 2px 10px;
      color: #fff;
      background-color: #07c170;
      font-size: 12px;
      border-radius: 3px;
    }

    button:disabled {
      color: rgba(16, 16, 16, 0.3);
      background-color: rgba(239, 239, 239, 0.3);
      cursor: not-allowed;
    }

    .lonlat>div {
      display: flex;
      padding: 15px;
      justify-content: space-between;
      border-bottom: 1px solid rgba(7, 193, 96, 0.4);
    }

    .dragBox {
      background-color: rgba(7, 193, 96, 0.4);
    }

    [v-cloak] {
      display: none;
    }
  </style>
</head>

<body>
  <div id="app" v-cloak>
    <div id="map" @mousemove='handleMouseMoveOnMap' @mouseenter='handleMouseMoveOnMap'
      @mouseleave='handleMouseLeaveOnMap'></div>
    <p :style='{left: clientX, top: clientY}'>按住鼠标左键拖拽框选</p>
    <div id="info">
      <button @click='handleClickSelectMap' :disabled='isDisabled'>地图上框选范围</button>
      <div class="lonlat">
        <div>
          <span>左上角经度：</span>
          <span>{{lonlat1[0]}}</span>
        </div>
        <div>
          <span>左上角纬度：</span>
          <span>{{lonlat1[1]}}</span>
        </div>
        <div>
          <span>右下角经度：</span>
          <span>{{lonlat2[0]}}</span>
        </div>
        <div>
          <span>右下角纬度：</span>
          <span>{{lonlat2[1]}}</span>
        </div>
      </div>
    </div>
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/8.2.0/dist/ol.min.js"
    integrity="sha512-+nvfloZUX7awRy1yslYBsicmHKh/qFW5w79+AiGiNcbewg0nBy7AS4G3+aK/Rm+eGPOKlO3tLuVphMxFXeKeOQ=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.14/vue.global.prod.min.js"
    integrity="sha512-huEQFMCpBzGkSDSPVAeQFMfvWuQJWs09DslYxQ1xHeaCGQlBiky9KKZuXX7zfb0ytmgvfpTIKKAmlCZT94TAlQ=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script>
    const { createApp } = Vue;
    const vm = createApp({
      data() {
        return {
          map: {}, // 地图实例
          isDisabled: false, // 按钮状态 框选中
          dragBox: {}, // 拖拽框选实例
          lonlat1: [], // 左上角经纬度
          lonlat2: [], // 右下角经纬度
          clientX: '-100%', // 提示信息left值
          clientY: '-100%' // 提示信息top值
        }
      },
      methods: {
        // 初始化地图
        initMap() {
          // 高德地图瓦片地址
          const amapVectorLayer = new ol.layer.Tile({
            source: new ol.source.XYZ({
              url: 'http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'
            })
          });
          this.map = new ol.Map({
            target: 'map',
            layers: [amapVectorLayer],
            view: new ol.View({
              center: [12129346.151443446, 4217286.994156892],
              zoom: 5
            })
          });
          // 绑定地图点击事件，打印经纬度
          this.map.on('click', (e) => {
            const point = ol.proj.transform(e.coordinate, 'EPSG:3857', 'EPSG:4326')
            console.log(`经度:${point[0].toFixed(6)} 纬度:${point[1].toFixed(6)}`);
          });
        },
        // 鼠标点击按钮，创建拖拽实例，绑定拖拽结束事件
        handleClickSelectMap() {
          this.isDisabled = true;
          this.dragBox = new ol.interaction.DragBox({
            className: 'dragBox', // 可自定义css样式
            // condition: ol.events.condition.platformModifierKeyOnly, // ctrl
            condition: ol.events.condition.noModifierKeys,
          });
          this.map.addInteraction(this.dragBox);
          this.dragBox.on('boxend', (e) => {
            this.isDisabled = false;
            const boxExtent = this.dragBox.getGeometry().getExtent();
            this.lonlat1 = ol.proj.transform([boxExtent[0], boxExtent[1]], 'EPSG:3857', 'EPSG:4326').map(e => e.toFixed(6));
            this.lonlat2 = ol.proj.transform([boxExtent[2], boxExtent[3]], 'EPSG:3857', 'EPSG:4326').map(e => e.toFixed(6));
            this.map.removeInteraction(this.dragBox); // 框选解释，删除拖拽款选交互
            this.handleMouseLeaveOnMap(); // 框选结束，隐藏提示信息
          });
          dragBox.on('boxstart', function () {
            console.log('===========开始框选===========');
          });
        },
        // 地图绑定鼠标移动事件，提示拖拽框选方法
        handleMouseMoveOnMap(e) {
          if (!this.isDisabled) {
            return;
          }
          this.clientX = e.clientX + 'px';
          this.clientY = e.clientY + 'px';
        },
        // 鼠标离开地图，隐藏提示信息
        handleMouseLeaveOnMap() {
          this.clientX = '-100%';
          this.clientY = '-100%';
        }
      },
      mounted() {
        this.initMap();
      }
    }).mount('#app');
  </script>
</body>

</html>